﻿/****************************************************************
* MACHINE: DESKTOP-I6HF1HG
* NAME: gjp
* CREATEDATE: 2019/3/4 15:28:14
* DESC: <DESCRIPTION>
* **************************************************************/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using iText.Kernel.Geom;
using iText.Kernel.Pdf;
using iText.Layout;
using iText.Layout.Element;

namespace LEE.Tools.IO
{
    /// <summary>
    /// Summary description for PdfHelper
    /// </summary>
    public static class PdfHelper
    {
        /// <summary>
        /// 把列表数据保存到Pdf数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <returns></returns>
        public static byte[] ToPdfData<T>(this List<T> list) where T : class
        {
            var ms = new MemoryStream();
            var writer = new PdfWriter(ms);
            var pdf = new PdfDocument(writer);
            var document = new Document(pdf, PageSize.A4.Rotate());

            try
            {
                document.SetTextAlignment(iText.Layout.Properties.TextAlignment.CENTER);
                document.SetMargins(20, 20, 20, 20);
                var type = typeof(T);
                var headers = GetColumnNames(type);
                var properties = type.GetProperties();
                if (headers == null || headers.Count == 0) return null;

                var table = new Table(headers.Count);

                foreach (var header in headers)
                {
                    table.WriteCell(header.Item1);
                }

                foreach (var item in list)
                {
                    foreach (var header in headers)
                    {
                        var property = properties.FirstOrDefault(x => x.Name == header.Item2);
                        var val = property == null ? "" : property.GetValue(item)?.ToString();
                        table.WriteCell(val);
                    }
                }

                return ms.ToArray();
            }
            finally
            {
                document.Close();
                ms.Dispose();
            }
        }

        /// <summary>
        /// 把列表数据保存到Pdf文件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <param name="filePath"></param>
        public static void SaveToPdfFile<T>(this List<T> list, string filePath) where T : class
        {
            var data = ToPdfData(list);
            File.WriteAllBytes(filePath, data);
        }

        private static void WriteCell(this Table table, string val)
        {
            var cell = new Cell();
            cell.SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.MIDDLE);
            cell.SetHorizontalAlignment(iText.Layout.Properties.HorizontalAlignment.CENTER); //水平居中
            cell.SetVerticalAlignment(iText.Layout.Properties.VerticalAlignment.MIDDLE); //垂直居中
            cell.Add(new Paragraph(val));
            table.AddCell(cell);
        }

        /// <summary>
        /// 获取列标题
        /// </summary>
        /// <param name="type"></param>
        /// <param name="includeReference"></param>
        /// <returns>显示名称，真实属性名称</returns>
        private static List<Tuple<string, string>> GetColumnNames(Type type, bool includeReference = false)
        {
            var result = new List<Tuple<string, string>>();
            var properties = type.GetProperties();
            var stringType = typeof(string);
            foreach (var item in properties)
            {
                if (!(item.PropertyType.IsValueType || item.PropertyType == stringType))
                {
                    if (!includeReference)
                        continue;
                }
                var display = item.GetCustomAttributes<DisplayNameAttribute>().FirstOrDefault();
                var displayName = display != null ? display.DisplayName : item.Name;
                result.Add(new Tuple<string, string>(displayName, item.Name));
            }
            return result;
        }
    }
}
